package com.gjy.service.uuid.service;

import com.fasterxml.uuid.Generators;
import com.fasterxml.uuid.NoArgGenerator;
import com.gjy.service.uuid.algorithm.SnowflakeIdGenerator;
import com.gjy.service.uuid.event.UuidEvent;
import com.gjy.service.uuid.util.IdMappingUtil;
import com.lmax.disruptor.RingBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author gjy
 * @version 1.0
 * @since 2025-10-12 10:21:55
 */
@Service
public class UuidGeneratorService {

    private static final Logger logger = LoggerFactory.getLogger(UuidGeneratorService.class);

    @Resource
    private RingBuffer<UuidEvent> ringBuffer;

    // 使用java-uuid-generator生成UUID
    private final NoArgGenerator uuidGenerator = Generators.randomBasedGenerator();
    // 雪花算法ID生成器缓存
    private final ConcurrentHashMap<String, SnowflakeIdGenerator> snowflakeGenerators = new ConcurrentHashMap<>();

    /**
     * 生成单个UUID
     *
     * @return 生成的UUID字符串
     */
    public String generateUuid() {
        UUID uuid = uuidGenerator.generate();
        String uuidString = uuid.toString();

        // 发布事件到Disruptor队列
        publishUuidEvent(uuidString, null);

        return uuidString;
    }

    /**
     * 生成指定数量的UUID
     *
     * @param count 生成数量
     * @return UUID字符串数组
     */
    public String[] generateUuids(int count) {
        if (count <= 0) {
            throw new IllegalArgumentException("Count must be positive");
        }

        String[] uuids = new String[count];
        for (int i = 0; i < count; i++) {
            UUID uuid = uuidGenerator.generate();
            uuids[i] = uuid.toString();

            // 发布事件到Disruptor队列
            publishUuidEvent(uuids[i], String.valueOf(i));
        }

        return uuids;
    }

    /**
     * 生成基于时间的UUID
     *
     * @return 基于时间的UUID字符串
     */
    public String generateTimeBasedUuid() {
        UUID uuid = Generators.timeBasedGenerator().generate();
        String uuidString = uuid.toString();

        // 发布事件到Disruptor队列
        publishUuidEvent(uuidString, "time-based");

        return uuidString;
    }

    /**
     * 发布UUID事件到Disruptor队列
     *
     * @param uuid      生成的UUID
     * @param requestId 请求ID
     */
    private void publishUuidEvent(String uuid, String requestId) {
        try {
            // 获取下一个序列号
            long sequence = ringBuffer.next();

            try {
                // 获取事件对象
                UuidEvent event = ringBuffer.get(sequence);

                // 设置事件数据
                event.setUuid(uuid);
                event.setTimestamp(System.currentTimeMillis());
                event.setRequestId(requestId);

            } finally {
                // 发布事件
                ringBuffer.publish(sequence);
            }

        } catch (Exception e) {
            logger.error("Failed to publish UUID event for uuid: {}", uuid, e);
        }
    }

    /**
     * 使用雪花算法生成唯一编码
     *
     * @param systemCode   系统编码 (如: CHT_JS)
     * @param machineCode  机器编码 (如: 192.168.253.111)
     * @param instanceCode 实例编码 (如: 1)
     * @return 生成的唯一编码
     */
    public String generateSnowflakeId(String systemCode, String machineCode, String instanceCode) {
        try {
            // 获取雪花算法生成器
            SnowflakeIdGenerator generator = getSnowflakeGenerator(systemCode, machineCode, instanceCode);

            // 生成ID
            long id = generator.nextId();
            String idString = String.valueOf(id);

            // 发布事件到Disruptor队列
            publishUuidEvent(idString, String.format("snowflake-%s-%s-%s", systemCode, machineCode, instanceCode));

            logger.debug("生成雪花算法ID: {} (系统: {}, 机器: {}, 实例: {})", idString, systemCode, machineCode, instanceCode);

            return idString;

        } catch (Exception e) {
            logger.error("生成雪花算法ID失败 - 系统: {}, 机器: {}, 实例: {}", systemCode, machineCode, instanceCode, e);
            throw new RuntimeException("生成雪花算法ID失败", e);
        }
    }

    /**
     * 批量生成雪花算法ID
     *
     * @param systemCode   系统编码
     * @param machineCode  机器编码
     * @param instanceCode 实例编码
     * @param count        生成数量
     * @return 生成的ID数组
     */
    public String[] generateSnowflakeIds(String systemCode, String machineCode, String instanceCode, int count) {
        if (count <= 0) {
            throw new IllegalArgumentException("生成数量必须大于0");
        }
        if (count > 10000) {
            throw new IllegalArgumentException("单次生成数量不能超过10000个");
        }

        try {
            // 获取雪花算法生成器
            SnowflakeIdGenerator generator = getSnowflakeGenerator(systemCode, machineCode, instanceCode);

            String[] ids = new String[count];
            for (int i = 0; i < count; i++) {
                long id = generator.nextId();
                ids[i] = String.valueOf(id);

                // 发布事件到Disruptor队列
                publishUuidEvent(ids[i], String.format("snowflake-batch-%s-%s-%s-%d", systemCode, machineCode, instanceCode, i));
            }

            logger.info("批量生成雪花算法ID完成 - 数量: {}, 系统: {}, 机器: {}, 实例: {}", count, systemCode, machineCode, instanceCode);

            return ids;

        } catch (Exception e) {
            logger.error("批量生成雪花算法ID失败 - 数量: {}, 系统: {}, 机器: {}, 实例: {}", count, systemCode, machineCode, instanceCode, e);
            throw new RuntimeException("批量生成雪花算法ID失败", e);
        }
    }

    /**
     * 解析雪花算法ID，获取各个组成部分
     *
     * @param id 雪花算法ID
     * @return ID组件信息
     */
    public SnowflakeIdGenerator.IdComponents parseSnowflakeId(String id) {
        try {
            long idLong = Long.parseLong(id);

            // 使用默认的雪花算法生成器来解析
            // 这里使用系统编码和机器编码都为0的生成器来解析
            SnowflakeIdGenerator generator = new SnowflakeIdGenerator(0, 0);
            return generator.parseId(idLong);

        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("无效的雪花算法ID格式: " + id);
        } catch (Exception e) {
            logger.error("解析雪花算法ID失败: {}", id, e);
            throw new RuntimeException("解析雪花算法ID失败", e);
        }
    }

    /**
     * 获取雪花算法生成器（带缓存）
     *
     * @param systemCode   系统编码
     * @param machineCode  机器编码
     * @param instanceCode 实例编码
     * @return 雪花算法生成器
     */
    private SnowflakeIdGenerator getSnowflakeGenerator(String systemCode, String machineCode, String instanceCode) {
        // 生成缓存键
        String cacheKey = String.format("%s-%s-%s", systemCode, machineCode, instanceCode);

        return snowflakeGenerators.computeIfAbsent(cacheKey, key -> {
            try {
                // 获取系统ID
                long systemId = IdMappingUtil.getSystemId(systemCode);

                // 获取机器ID
                long machineId = IdMappingUtil.getMachineId(machineCode);

                // 获取实例ID
                long instanceId = IdMappingUtil.getInstanceId(instanceCode);

                // 组合机器ID和实例ID (机器ID占高5位，实例ID占低5位)
                long combinedMachineId = ((machineId & 0x1) << 4) | (instanceId & 0xF);

                // 创建雪花算法生成器
                SnowflakeIdGenerator generator = new SnowflakeIdGenerator(systemId, combinedMachineId);

                logger.info("创建雪花算法生成器 - 缓存键: {}, 系统ID: {}, 机器ID: {}, 实例ID: {}", cacheKey, systemId, machineId, instanceId);

                return generator;

            } catch (Exception e) {
                logger.error("创建雪花算法生成器失败 - 系统: {}, 机器: {}, 实例: {}", systemCode, machineCode, instanceCode, e);
                throw new RuntimeException("创建雪花算法生成器失败", e);
            }
        });
    }

    /**
     * 获取雪花算法生成器统计信息
     *
     * @return 生成器统计信息
     */
    public java.util.Map<String, Object> getSnowflakeGeneratorStats() {
        java.util.Map<String, Object> stats = new java.util.HashMap<>();
        stats.put("generatorCount", snowflakeGenerators.size());
        stats.put("generatorKeys", snowflakeGenerators.keySet());
        stats.put("systemMappings", IdMappingUtil.getAllSystemMappings());
        stats.put("machineMappings", IdMappingUtil.getAllMachineMappings());
        return stats;
    }

}
